/**************************************************************************************
 *
 * @(#) ApiAspect.java
 * @Package com.jgdt.jgdtkasannong_university_gene_backend.aspect.idempotent
 **************************************************************************************/
package com.jgdt.jgdtkasannong_university_gene_backend.aspect.idempotent;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.jgdt.jgdtkasannong_university_gene_backend.common.Sysconstant;
import com.jgdt.jgdtkasannong_university_gene_backend.common.enums.BusinessCodeEnums;
import com.jgdt.jgdtkasannong_university_gene_backend.common.example.custom.BusinessException;
import com.jgdt.jgdtkasannong_university_gene_backend.utils.RedisUtils;
import com.jgdt.jgdtkasannong_university_gene_backend.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @description: api接口幂等控制
 * @author: huangAn
 * @createDate: 2025/04/29
 */
@Component
@Slf4j
@Aspect
public class ApiIdempotentAspect {

    @Autowired
    private RedisUtils redisUtils;

    /**
     * 前置增强，目标方法执行之前执行 within:用于匹配所以持有指定注解类型内的方法 annotation:用于匹配当前执行方法持有指定注解的方法
     * within(com.xxx.xxx..*) com.xxx.xxx包及子包下的任何方法执行
     * @param joinPoint
     * @param apiIdempotent
     */
    @Before("within(com.jgdt..*) && @annotation(apiIdempotent)")
    public void addBeforeApiIdempotent(JoinPoint joinPoint, ApiIdempotent apiIdempotent) {
        if (StringUtils.isEmpty(apiIdempotent.apiNameCode())) {
            log.warn("addBeforeApiIdempotent warn:apiNameCode 为空...");
            return;
        }
        //获取当前用户
        String userName = SecurityUtils.getCurrentUsername();
        String redisKeyIndex = userName + apiIdempotent.apiNameCode();
        String redisKey = Sysconstant.API_USER_IDEMPOTENT_KEY + redisKeyIndex;

        Object result = redisUtils.get(redisKey);
        if (ObjectUtils.isNotEmpty(result)) {
            //缓存存在
            throw new BusinessException(BusinessCodeEnums.API_IDEMPOTENT_ERR.getKey(), apiIdempotent.apiErrMsg());
        } else {
            //存入缓存
            redisUtils.set(redisKey, redisKey, Long.valueOf(apiIdempotent.idempotentTime()));
        }
    }
}




